home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / worst102.zip / WORST.C < prev    next >
C/C++ Source or Header  |  1992-08-01  |  12KB  |  692 lines

  1. /* File: WORST.C */
  2.  
  3. #define    VERSION    "1.02"
  4.  
  5. /*
  6.     Written by Dan Lewis and released to the public domain.
  7.     Compiled using the C-Ware (DeSmet) DC88 compiler and the
  8.     -px switch, bound (linked) using C-Ware (DeSmet) BIND.
  9. */
  10.  
  11. #ifdef    _lint
  12. #include "\lint\sl-desm.c"
  13. #else
  14. #include <stdio.h>
  15. #endif
  16.  
  17. #ifndef    CALL
  18. #define    CALL    (void)
  19. #endif
  20.  
  21. typedef unsigned    BOOL ;
  22. typedef unsigned char    BYTE ;
  23. typedef unsigned int    WORD ;
  24. typedef    long        DUBL ;
  25.  
  26. #define    READ_ONLY    0x01
  27. #define    HIDDEN        0x02
  28. #define    SYSTEM        0x04
  29. #define    VOL_LABEL    0x08
  30. #define    DIR_ENTRY    0x10
  31. #define    ARCHIVE        0x20
  32.  
  33. #define    FIRST        0x4E
  34. #define    NEXT        0x4F
  35.  
  36. typedef struct TIME
  37.     {
  38.     unsigned
  39.     hsec:5,        /* seconds/2 (0-29)    */
  40.     min:6,        /* minute (0-59)    */
  41.     hour:5 ;    /* hour (0-23)    */
  42.     } TIME ;
  43.  
  44. typedef struct DATE
  45.     {
  46.     unsigned
  47.         day:5,        /* day (1-31)    */
  48.         month:4,    /* month (1-12)    */
  49.         year:7 ;    /* year - 1980    */
  50.     } DATE ;
  51.  
  52. typedef struct DTA
  53.     {
  54.     char    rsvd[21] ;
  55.     char    attb ;
  56.     TIME    time ;
  57.     DATE    date ;
  58.     long    size ;
  59.     char    name[13] ;
  60.     } DTA ;
  61.  
  62. typedef struct STAT
  63.     {
  64.     char    *name ;
  65.     char    file[100] ;
  66.     TIME    time ;
  67.     DATE    date ;
  68.     DUBL    size ;
  69.     } STAT ;
  70.  
  71. #define    SAME(s1, s2)    !strcmp(s1, s2)
  72. #define    ENDCHAR(s)    s[strlen(s) - 1]
  73. #define    SLASH(c)    (c == '\\' || c == '/')
  74.  
  75. BOOL found = FALSE ;
  76. char *slash ;
  77.  
  78. #define    NONE    "[ none ]"
  79.  
  80. STAT empty_f    = {"Empty",    NONE} ;
  81. STAT newest_f   = {"Newest",    NONE} ;
  82. STAT oldest_f   = {"Oldest",    NONE} ;
  83. STAT largest_f  = {"Largest",    NONE} ;
  84. STAT smallest_f = {"Smallest",    NONE} ;
  85.  
  86. STAT empty_d    = {"Empty",    NONE} ;
  87. STAT newest_d   = {"Newest",    NONE} ;
  88. STAT oldest_d   = {"Oldest",    NONE} ;
  89. STAT largest_d  = {"Largest",    NONE} ;
  90. STAT smallest_d = {"Smallest",    NONE} ;
  91.  
  92. void Set_DTA(DTA *) ;
  93. BOOL Find(WORD, char *, WORD) ;
  94. void Replace(STAT *, char *, DTA *) ;
  95. void Header(char *) ;
  96. char *Time(TIME *) ;
  97. char *Date(DATE *) ;
  98. DUBL Search(char *, BOOL) ;
  99. void Display(STAT *) ;
  100. void Extract_Prefix(char *, char *) ;
  101. void Split(char *, char *, char *) ;
  102. void Update_Files(char *, DTA *) ;
  103. void Update_Dirs(char *, DTA *) ;
  104. DUBL Contents(char *) ;
  105. void Working(char *) ;
  106. void Set_Vector(unsigned, ...) ;
  107. DUBL Get_Vector(unsigned) ;
  108. void pokew(WORD, ...) ;
  109. void poked(DUBL, ...) ;
  110.  
  111. /*lint -e715 */
  112. void Set_DTA(dta)
  113. DTA *dta ;
  114.     {
  115. #ifndef    _lint
  116. #asm
  117.     mov    ah,1Ah
  118.     mov    dx,#dta
  119.     int    21h
  120. #end
  121. #endif
  122.     }
  123.  
  124. BOOL Find(mode, spec, attb)
  125. WORD mode ;
  126. char *spec ;
  127. WORD attb ;
  128.     {
  129. #ifndef    _lint
  130. #asm
  131.     mov    ah,#mode
  132.     xor    al,al
  133.     mov    cx,#attb
  134.     mov    dx,#spec
  135.     int    21h
  136.     mov    ax,0
  137.     jc    Fail1
  138.     inc    ax
  139. Fail1:
  140. #end
  141. #endif
  142.     }
  143. /*lint +e715 */
  144.  
  145. void Replace(stat, pfx, dta)
  146. STAT *stat ;
  147. char *pfx ;
  148. DTA *dta ;
  149.     {
  150.     strcpy(stat->file, pfx) ;
  151.     strcat(stat->file, dta->name) ;
  152.     stat->time = dta->time ;
  153.     stat->date = dta->date ;
  154.     stat->size = dta->size ;
  155.     found = TRUE ;
  156.     }
  157.  
  158. void Banner()
  159.     {
  160.     char bfr[80] ;
  161.     sprintf(bfr, "\nWORST v%s - Last revision date: %s  ",
  162.         VERSION, __DATE__) ;
  163.     Working(bfr) ;
  164.     }
  165.  
  166. void Header(type)
  167. char *type ;
  168.     {
  169.     printf("\n") ;
  170.     printf("Category   Date    Time      Bytes %s\n", type) ;
  171.     printf("-------- -------- ------ --------- -----------------------") ;
  172.     printf("\n") ;
  173.     }
  174.  
  175. char *Time(t)
  176. TIME *t ;
  177.     {
  178.     static char time[7] ;
  179.     char ampm ;
  180.  
  181.     if (t->hour >= 12)
  182.         {
  183.         t->hour -= 12 ;
  184.         ampm = 'p' ;
  185.         }
  186.     else ampm = 'a' ;
  187.     sprintf(time, "%2u:%02u%c", t->hour, t->min, ampm) ;
  188.     return time ;
  189.     }
  190.  
  191. char *Date(d)
  192. DATE *d ;
  193.     {
  194.     static char date[9] ;
  195.  
  196.     sprintf(date, "%2u-%02u-%02u", d->month, d->day,
  197.         (d->year + 1980) % 100) ;
  198.     return date ;
  199.     }
  200.  
  201. void Extract_Prefix(head, pfx)
  202. char *head ;
  203. char *pfx ;
  204.     {
  205.     char *p ;
  206.  
  207.     strcpy(pfx, head) ;
  208.     p = &pfx[strlen(head)] ;
  209.     while (p >= pfx)
  210.         {
  211.         switch (p[0])
  212.             {
  213.             case '?':
  214.             case '*':
  215.                 p[0] = '\0' ;
  216.                 break ;
  217.  
  218.             case '\\':
  219.             case '/':
  220.             case ':':
  221.                 p[1] = '\0' ;
  222.                 return ;
  223.             }
  224.         p-- ;
  225.         }
  226.     }
  227.  
  228. void Split(spec, head, tail)
  229. char *spec ;
  230. char *head ;
  231. char *tail ;
  232.     {
  233.     unsigned state ;
  234.     char ch, *p ;
  235.  
  236.  
  237.     state = 1 ;
  238.     *tail = '\0' ;
  239.     p = head ;
  240.     while ((ch = *spec++) != '\0')
  241.         {
  242.         switch (ch)
  243.             {
  244.             case '*':
  245.             case '?':
  246.                 if (state == 1) state = 2 ;
  247.                 break ;
  248.  
  249.             case '\\':
  250.             case '/':
  251.                 if (state != 2) break ;
  252.                 *p = '\0' ;
  253.                 p = tail ;
  254.                 state = 3 ;
  255.                 break ;
  256.             }
  257.         *p++ = ch ;
  258.         }
  259.  
  260.     *p = '\0' ;
  261.     }
  262.  
  263. #define    NEWER(a, b)    (*((DUBL *) &a->time) >= *((DUBL *) &b.time))
  264. #define    OLDER(a, b)    (*((DUBL *) &a->time) <= *((DUBL *) &b.time))
  265.  
  266. void Update_Files(pfx, dta)
  267. char *pfx ;
  268. DTA *dta ;
  269.     {
  270.     if (NEWER(dta, newest_f)) Replace(&newest_f, pfx, dta) ;
  271.     if (OLDER(dta, oldest_f)) Replace(&oldest_f, pfx, dta) ;
  272.  
  273.     if (dta->size > largest_f.size)  Replace(&largest_f,  pfx, dta) ;
  274.     else if (dta->size == largest_f.size && OLDER(dta, largest_f))
  275.         {
  276.         Replace(&largest_f,  pfx, dta) ;
  277.         }
  278.  
  279.     if (dta->size == 0L)
  280.         {
  281.         if (OLDER(dta, empty_f))  Replace(&empty_f, pfx, dta) ;
  282.         }
  283.     else if (dta->size < smallest_f.size) Replace(&smallest_f, pfx, dta);
  284.     else if (dta->size == smallest_f.size && OLDER(dta, smallest_f))
  285.         {
  286.         Replace(&smallest_f, pfx, dta);
  287.         }
  288.     }
  289.  
  290. void Update_Dirs(pfx, dta)
  291. char *pfx ;
  292. DTA *dta ;
  293.     {
  294.     if (NEWER(dta, newest_d)) Replace(&newest_d, pfx, dta) ;
  295.     if (OLDER(dta, oldest_d)) Replace(&oldest_d, pfx, dta) ;
  296.  
  297.     if (dta->size > largest_d.size)  Replace(&largest_d,  pfx, dta) ;
  298.     else if (dta->size == largest_d.size && OLDER(dta, largest_d))
  299.         {
  300.         Replace(&largest_d,  pfx, dta) ;
  301.         }
  302.  
  303.     if (dta->size == 0L)
  304.         {
  305.         if (OLDER(dta, empty_d))  Replace(&empty_d, pfx, dta) ;
  306.         }
  307.     else if (dta->size < smallest_d.size) Replace(&smallest_d, pfx, dta);
  308.     else if (dta->size == smallest_d.size && OLDER(dta, smallest_d))
  309.         {
  310.         Replace(&smallest_d, pfx, dta);
  311.         }
  312.     }
  313.  
  314. DUBL Search(spec, recurse)
  315. char *spec ;
  316. BOOL recurse ;
  317.     {
  318.     char *pfx, *head, *tail ;
  319.     unsigned find ;
  320.     DUBL bytes ;
  321.     DTA *dta ;
  322.  
  323.     bytes = 0L ;
  324.  
  325.     head = malloc(strlen(spec) + 1) ;
  326.     tail = malloc(strlen(spec) + 1) ;
  327.     Split(spec, head, tail) ;
  328.  
  329.     pfx = malloc(strlen(head) + 1) ;
  330.     Extract_Prefix(head, pfx) ;
  331.  
  332.     dta = malloc(sizeof(DTA)) ;
  333.     Set_DTA(dta) ;
  334.  
  335.     find = FIRST ;
  336.     while (Find(find, head, DIR_ENTRY))
  337.         {
  338.         find = NEXT ;
  339.  
  340.         if (SAME(dta->name, "."))    continue ;
  341.         if (SAME(dta->name, ".."))    continue ;
  342.         if (!(dta->attb & DIR_ENTRY))    continue ;
  343.  
  344.         strcpy(spec, pfx) ;
  345.         strcat(spec, dta->name) ;
  346.  
  347.         if (SAME(tail, ""))
  348.             {
  349.             dta->size = Contents(spec) ;
  350.             if (recurse)
  351.                 {
  352.                 strcat(spec, slash) ;
  353.                 strcat(spec, "*.*") ;
  354.                 bytes += Search(spec, recurse) ;
  355.                 }
  356.             Update_Dirs(pfx, dta) ;
  357.             }
  358.         else
  359.             {
  360.             strcat(spec, tail) ;
  361.             bytes += Search(spec, recurse) ;
  362.             }
  363.         Set_DTA(dta) ;
  364.         }
  365.  
  366.     if (SAME(tail, ""))
  367.         {
  368.         find = FIRST ;
  369.         while (Find(find, head, HIDDEN|SYSTEM))
  370.             {
  371.             find = NEXT ;
  372.             bytes += dta->size ;
  373.             Update_Files(pfx, dta) ;
  374.             }
  375.         }
  376.  
  377.     CALL free(head) ;
  378.     CALL free(tail) ;
  379.     CALL free(pfx) ;
  380.     CALL free(dta) ;
  381.  
  382.     return bytes ;
  383.     }
  384.  
  385. DUBL Contents(dir)
  386. char *dir ;
  387.     {
  388.     unsigned find ;
  389.     DTA *dta ;
  390.     DUBL bytes ;
  391.     char *spec ;
  392.  
  393.  
  394.     bytes = 0 ;
  395.     dta = malloc(sizeof(DTA)) ;
  396.     spec = malloc(strlen(dir) + 14) ;
  397.     strcpy(spec, dir) ;
  398.     strcat(spec, slash) ;
  399.     strcat(spec, "*.*") ;
  400.  
  401.     Set_DTA(dta) ;
  402.     find = FIRST ;
  403.     while (Find(find, spec, HIDDEN|SYSTEM|DIR_ENTRY))
  404.         {
  405.         find = NEXT ;
  406.  
  407.         if (SAME(dta->name, "."))    continue ;
  408.         if (SAME(dta->name, ".."))    continue ;
  409.  
  410.         if (dta->attb & DIR_ENTRY)
  411.             {
  412.             strcpy(spec, dir) ;
  413.             strcat(spec, slash) ;
  414.             strcat(spec, dta->name) ;
  415.             bytes += Contents(spec) ;
  416.             Set_DTA(dta) ;
  417.             }
  418.         else bytes += dta->size ;
  419.         }
  420.  
  421.     CALL free(dta) ;
  422.     CALL free(spec) ;
  423.  
  424.     return bytes ;
  425.     }
  426.  
  427. void Display(stat)
  428. STAT *stat ;
  429.     {
  430.     if (SAME(stat->file, NONE)) return ;
  431.  
  432.     printf("%-8s %s %s %9lu %s\n",
  433.         stat->name,
  434.         Date(&stat->date),
  435.         Time(&stat->time),
  436.         stat->size,
  437.         stat->file) ;
  438.     }
  439.  
  440. void main(argc, argv)
  441. unsigned argc ;
  442. char **argv ;
  443.     {
  444.     static char spec[100] ;
  445.     BOOL recurse, searched ;
  446.     unsigned arg ;
  447.  
  448.  
  449.     Banner() ;
  450.  
  451.     smallest_f.size = 0x7FFFFFFFL ;
  452.     *((DUBL *) &oldest_f.time)   = 0x7FFFFFFFL ;
  453.     *((DUBL *) &empty_f.time)   = 0x7FFFFFFFL ;
  454.  
  455.     smallest_d.size = 0x7FFFFFFFL ;
  456.     *((DUBL *) &oldest_d.time)   = 0x7FFFFFFFL ;
  457.     *((DUBL *) &empty_d.time)   = 0x7FFFFFFFL ;
  458.  
  459.     slash = "\\" ;
  460.     for (arg = 1; arg < argc; arg++)
  461.         {
  462.         if (!strchr(argv[arg], '/')) continue ;
  463.         slash = "/" ;
  464.         break ;
  465.         }
  466.  
  467.     recurse = searched = FALSE ;
  468.     for (arg = 1; arg < argc; arg++)
  469.         {
  470.         CALL strupr(argv[arg]) ;
  471.         if (SAME(argv[arg], "+S"))
  472.             {
  473.             recurse = TRUE ;
  474.             continue ;
  475.             }
  476.  
  477.         if (SAME(argv[arg], "-S"))
  478.             {
  479.             recurse = FALSE ;
  480.             continue ;
  481.             }
  482.  
  483.         strcpy(spec, argv[arg]) ;
  484.         Search(spec, recurse) ;
  485.         searched = TRUE ;
  486.         }
  487.  
  488.     if (!searched)
  489.         {
  490.         strcpy(spec, "*.*") ;
  491.         Search(spec, recurse) ;
  492.         }
  493.  
  494.     if (!found)
  495.         {
  496.         printf("\n\tNo matching directories/files!\7\n") ;
  497.         exit(0xFF) ;
  498.         }
  499.  
  500.     Working(NULL) ;
  501.     printf("\n") ;
  502.  
  503.     Header("Directory") ;
  504.     Display(&empty_d) ;
  505.     Display(&smallest_d) ;
  506.     Display(&largest_d) ;
  507.     Display(&oldest_d) ;
  508.     Display(&newest_d) ;
  509.  
  510.     Header("File") ;
  511.     Display(&empty_f) ;
  512.     Display(&smallest_f) ;
  513.     Display(&largest_f) ;
  514.     Display(&oldest_f) ;
  515.     Display(&newest_f) ;
  516.  
  517.     exit(0x00) ;
  518.     }
  519.  
  520. #define    WIDTH    75
  521. #define    MAXLEN    (WIDTH - 10)
  522.  
  523. BYTE    busy ;
  524. BYTE    width ;
  525. BYTE    fwd_count ;
  526. BYTE    rev_count ;
  527.  
  528. void    _Working() ;
  529. void    data_seg() ;
  530. void    chain() ;
  531.  
  532. void Dummy()
  533.     {
  534. #ifndef    _lint
  535. #asm
  536. data_seg_    dw    0
  537. chain_        dd    0
  538. ;---------
  539. _Working_:
  540. ;---------
  541.         sti
  542.         push    ax
  543.         push    ds
  544.         mov    ds,data_seg_
  545.  
  546.         mov    al,1
  547.         xchg    busy_,al
  548.         or    al,al
  549.         jnz    Skip_Tick
  550.  
  551.         push    bx
  552.         push    cx
  553.  
  554. Forward:    cmp    fwd_count_,0
  555.         je    Reverse
  556.         mov    ah,0Eh        ; write TTY
  557.         mov    al,'.'
  558.         mov    bx,7
  559.         int    10h
  560.         dec    fwd_count_
  561.         jnz    Finished
  562.         mov    al,width_
  563.         mov    rev_count_,al
  564.         jmp    Finished
  565.  
  566. Reverse:    cmp    rev_count_,0
  567.         je    Finished
  568.         mov    ax,0E08h    ; write backspace
  569.         mov    bx,7
  570.         int    10h
  571.         mov    ah,0Ah        ; write, no advance
  572.         mov    al,' '
  573.         xor    bh,bh
  574.         mov    cx,1
  575.         int    10h
  576.         dec    rev_count_
  577.         jnz    Finished
  578.         mov    al,width_
  579.         mov    fwd_count_,al
  580.  
  581. Finished:    mov    BYTE busy_,0
  582.         pop    cx
  583.         pop    bx
  584.  
  585. Skip_Tick:    pop    ds
  586.         pop    ax
  587.         cli
  588.         ljmp    DWORD chain_
  589. #end
  590. #endif
  591.     }
  592.  
  593. /*lint -e715 */
  594. DUBL Get_Vector(vector)
  595. unsigned vector ;
  596.     {
  597. #ifndef    _lint
  598. #asm
  599.         mov    ah,35h        ; get old vector
  600.         mov    al,#vector
  601.         int    21h
  602.         mov    ax,bx
  603.         mov    dx,es
  604. #end
  605. #endif
  606.     }
  607.  
  608. void Set_Vector(vector, off, seg)
  609. unsigned vector ;
  610. WORD off ;
  611. WORD seg ;
  612.     {
  613. #ifndef    _lint
  614. #asm
  615.         mov    ah,25h        ; Install new routine
  616.         mov    al,#vector
  617.         push    ds
  618.         mov    dx,#off
  619.         mov    ds,#seg
  620.         int    21h
  621.         pop    ds
  622. #end
  623. #endif
  624.     }
  625.  
  626. void pokew(word, off, seg)
  627. WORD word ;
  628. WORD off ;
  629. WORD seg ;
  630.     {
  631. #ifndef    _lint
  632. #asm
  633.     les    bx,#off
  634.     mov    ax,#word
  635.     mov    es:[bx],ax
  636. #end
  637. #endif
  638.     }
  639.  
  640. void poked(dubl, off, seg)
  641. DUBL dubl ;
  642. WORD off ;
  643. WORD seg ;
  644.     {
  645. #ifndef    _lint
  646. #asm
  647.     les    bx,#off
  648.     mov    ax,#dubl[0]
  649.     mov    es:[bx],ax
  650.     mov    ax,#dubl[2]
  651.     mov    es:[bx+2],ax
  652. #end
  653. #endif
  654.     }
  655. /*lint +e715 */
  656.  
  657. void Working(label)
  658. char *label ;
  659.     {
  660.     DUBL Get_Vector() ;
  661.     static DUBL old_int1c ;
  662.     static unsigned len = MAXLEN + 1 ;
  663.     WORD cs ;
  664.  
  665.     if (label != NULL)
  666.         {
  667.         printf(label) ;
  668.  
  669.         len = strlen(label) ;
  670.         if (len > MAXLEN) return ;
  671.  
  672.         fwd_count = width = (BYTE) (WIDTH - len) ;
  673.         rev_count = busy = 0 ;
  674.  
  675.         pokew(_showds(), (WORD) data_seg, cs = _showcs()) ;
  676.  
  677.         old_int1c = Get_Vector(0x1C) ;
  678.         poked(old_int1c, (WORD) chain, cs) ;
  679.         Set_Vector(0x1C, (WORD) _Working, cs) ;
  680.         }
  681.  
  682.     else
  683.         {
  684.         if (len > MAXLEN) return ;
  685.         Set_Vector(0x1C, old_int1c) ;
  686.         if (!isatty(fileno(stdout))) return ;
  687.         if (fwd_count) rev_count = (BYTE) (width - fwd_count) ;
  688.         while (rev_count-- > 0) printf("\b \b") ;
  689.         }
  690.     }
  691.  
  692.